package com.javacv.plus.extensions.batch;

import com.javacv.plus.extensions.image.ImageProcessor;
import com.javacv.plus.extensions.image.ProcessorResult;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.function.Function;

/**
 * 批量处理器
 * 支持图像和视频的批量处理
 */
@Slf4j
public class BatchProcessor {

    private final ExecutorService executorService;
    private final int maxConcurrency;

    public BatchProcessor() {
        this(Runtime.getRuntime().availableProcessors());
    }

    public BatchProcessor(int maxConcurrency) {
        this.maxConcurrency = maxConcurrency;
        this.executorService = Executors.newFixedThreadPool(maxConcurrency);
    }

    /**
     * 批量处理图像
     */
    public BatchResult<ProcessorResult> processImages(
            String inputDirectory,
            String outputDirectory,
            Function<String, ImageProcessor> processorFactory) {

        return processImages(inputDirectory, outputDirectory, processorFactory, 
                             new String[]{"jpg", "jpeg", "png", "bmp", "tiff"});
    }

    /**
     * 批量处理图像（指定扩展名）
     */
    public BatchResult<ProcessorResult> processImages(
            String inputDirectory,
            String outputDirectory,
            Function<String, ImageProcessor> processorFactory,
            String[] extensions) {

        log.info("开始批量处理图像 - 输入目录: {}, 输出目录: {}", inputDirectory, outputDirectory);

        File inputDir = new File(inputDirectory);
        File outputDir = new File(outputDirectory);

        // 创建输出目录
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        // 获取所有匹配的文件
        List<File> imageFiles = findFiles(inputDir, extensions);
        log.info("找到 {} 个图像文件", imageFiles.size());

        if (imageFiles.isEmpty()) {
            return new BatchResult<>(new ArrayList<>(), new ArrayList<>(), 0);
        }

        // 创建任务列表
        List<CompletableFuture<BatchTaskResult<ProcessorResult>>> futures = new ArrayList<>();

        for (File file : imageFiles) {
            String outputPath = new File(outputDir, file.getName()).getAbsolutePath();
            
            CompletableFuture<BatchTaskResult<ProcessorResult>> future = 
                CompletableFuture.supplyAsync(() -> {
                    try {
                        ImageProcessor processor = processorFactory.apply(file.getAbsolutePath());
                        ProcessorResult result = processor.save(outputPath);
                        return new BatchTaskResult<>(file.getAbsolutePath(), true, result, null);
                    } catch (Exception e) {
                        log.error("处理文件失败: {}", file.getAbsolutePath(), e);
                        return new BatchTaskResult<>(file.getAbsolutePath(), false, null, e.getMessage());
                    }
                }, executorService);

            futures.add(future);
        }

        // 等待所有任务完成
        return collectResults(futures);
    }

    /**
     * 批量转换图像格式
     */
    public BatchResult<ProcessorResult> convertImageFormat(
            String inputDirectory,
            String outputDirectory,
            String targetFormat) {

        return processImages(inputDirectory, outputDirectory, inputPath -> {
            String fileName = new File(inputPath).getName();
            String nameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.'));
            String outputPath = new File(outputDirectory, nameWithoutExt + "." + targetFormat).getAbsolutePath();
            
            return ImageProcessor.of(inputPath);
        });
    }

    /**
     * 批量调整图像大小
     */
    public BatchResult<ProcessorResult> resizeImages(
            String inputDirectory,
            String outputDirectory,
            int width,
            int height) {

        return processImages(inputDirectory, outputDirectory, inputPath -> 
            ImageProcessor.of(inputPath).resize(width, height));
    }

    /**
     * 批量添加水印
     */
    public BatchResult<ProcessorResult> addWatermarkToImages(
            String inputDirectory,
            String outputDirectory,
            String watermarkText) {

        return processImages(inputDirectory, outputDirectory, inputPath -> 
            ImageProcessor.of(inputPath).addTextWatermark(watermarkText));
    }

    /**
     * 查找指定扩展名的文件
     */
    private List<File> findFiles(File directory, String[] extensions) {
        List<File> result = new ArrayList<>();
        
        if (!directory.exists() || !directory.isDirectory()) {
            return result;
        }

        File[] files = directory.listFiles();
        if (files == null) {
            return result;
        }

        for (File file : files) {
            if (file.isFile()) {
                String fileName = file.getName().toLowerCase();
                for (String ext : extensions) {
                    if (fileName.endsWith("." + ext.toLowerCase())) {
                        result.add(file);
                        break;
                    }
                }
            } else if (file.isDirectory()) {
                // 递归处理子目录
                result.addAll(findFiles(file, extensions));
            }
        }

        return result;
    }

    /**
     * 收集处理结果
     */
    private <T> BatchResult<T> collectResults(List<CompletableFuture<BatchTaskResult<T>>> futures) {
        List<BatchTaskResult<T>> successResults = new ArrayList<>();
        List<BatchTaskResult<T>> failureResults = new ArrayList<>();

        long startTime = System.currentTimeMillis();

        try {
            CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0]));
            
            allFutures.get(); // 等待所有任务完成

            for (CompletableFuture<BatchTaskResult<T>> future : futures) {
                BatchTaskResult<T> result = future.get();
                if (result.isSuccess()) {
                    successResults.add(result);
                } else {
                    failureResults.add(result);
                }
            }

        } catch (InterruptedException | ExecutionException e) {
            log.error("批量处理过程中发生错误", e);
        }

        long processingTime = System.currentTimeMillis() - startTime;

        log.info("批量处理完成 - 成功: {}, 失败: {}, 耗时: {}ms", 
                successResults.size(), failureResults.size(), processingTime);

        return new BatchResult<>(successResults, failureResults, processingTime);
    }

    /**
     * 关闭批量处理器
     */
    public void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 获取最大并发数
     */
    public int getMaxConcurrency() {
        return maxConcurrency;
    }
} 